﻿using System;
using System.Collections.Generic;
using System.Text;
//new
using JRCore.enums;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
using JRCore.protocol;

namespace JRCore.tools
{
    /// <summary>
    /// TCP工作类
    /// </summary>
    public class StringServer
    {
        private bool m_exit;
        private Enum_TcpWorkMode m_mode;
        private string m_serverip;
        private string m_serverport;
        private string m_secretkey;
        private List<BinaryWriter> m_writerList;
        private List<BinaryReader> m_readerList;
        private TcpListener m_listen;
        private Thread m_ListernThread;//监听线程
        private int m_TimeOut;

        /// <summary>
        /// 服务端消息处理函数，重写本函数实现具体操作
        /// Read/ReadSend/SendRead模式下重写，Send模式下不需要重写
        /// </summary>
        /// <param name="send">Read模式send不使用,ReadSend模式send为输出，SendRead模式send为输入</param>
        /// <param name="read">Read/ReadSend/SendRead模式下，read为对方发送的消息</param>
        /// <param name="error">错误提示信息</param>
        /// <returns>处理结果</returns>
        public delegate bool RecordReceived(ref string send, string read, ref string error);

        /// <summary>
        /// 服务端消息处理函数，重写本函数实现具体操作
        /// Read/ReadSend/SendRead模式下重写，Send模式下不需要重写
        /// Read模式send不使用,ReadSend模式send为输出，SendRead模式send为输入
        /// Read/ReadSend/SendRead模式下，read为对方发送的消息
        /// </summary>
        public RecordReceived OnRecordReceived;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serverip">服务端IP</param>
        /// <param name="serverport">服务端PORT</param>
        /// <param name="mode">工作模式</param>
        public StringServer(string serverip, string serverport, Enum_TcpWorkMode mode)
        {
            try
            {
                m_TimeOut = 0;
                m_serverip = serverip;
                m_serverport = serverport;
                m_mode = mode;
                m_secretkey = SecretKey.GetKey(m_serverip);
                m_writerList = new List<BinaryWriter>();
                m_readerList = new List<BinaryReader>();
                OnRecordReceived = new RecordReceived(RecordReceivedFunc);
                //启动监听线程
                m_listen = new TcpListener(IPAddress.Parse(m_serverip), int.Parse(m_serverport));
                m_ListernThread = new Thread(new ParameterizedThreadStart(ListernThreadFunc));
                m_ListernThread.IsBackground = true;
                m_ListernThread.Start(m_listen);
            }
            catch { }
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            m_exit = true;

            try
            {
                if (m_writerList != null)
                {
                    foreach (BinaryWriter bw in m_writerList)
                    {
                        bw.Close();
                    }
                    m_writerList.Clear();
                }
            }
            catch { }

            try
            {
                if (m_readerList != null)
                {
                    foreach (BinaryReader br in m_readerList)
                    {
                        br.Close();
                    }
                    m_readerList.Clear();
                }
            }
            catch { }

            try
            {
                if (m_listen != null)
                {
                    m_listen.Stop();
                    if (m_listen.Server != null)
                    {
                        m_listen.Server.Shutdown(SocketShutdown.Both);
                        m_listen.Server.Close();
                    }
                    m_listen = null;
                }
            }
            catch { }

            try
            {
                m_ListernThread.Abort();
                m_ListernThread.Join(3000);
            }
            catch { }

            GC.Collect();
        }

        private void ListernThreadFunc(object obj)
        {
            TcpListener listen = (TcpListener)obj;
            bool flag = false;//监听是否建立
            bool shown = false;
            while (!m_exit)
            {
                try
                {
                    if (flag == false)
                    {
                        try
                        {
                            listen.Start();
                            flag = true;
                            Console.WriteLine("启动监听");
                        }
                        catch (SocketException)
                        {
                            flag = false;
                            if (shown == false)
                            {
                                Console.WriteLine("监听失败");
                                shown = true;
                            }
                        }
                    }

                    if ((flag == true) && (listen.Pending() == true))
                    {
                        TcpClient tcpclient = listen.AcceptTcpClient();
                        if (m_TimeOut > 0)
                        {
                            tcpclient.SendTimeout = m_TimeOut;
                            tcpclient.ReceiveTimeout = m_TimeOut;
                        }
                        Thread DealTcpClientThread = new Thread(new ParameterizedThreadStart(DealTcpClientThreadFunc));
                        DealTcpClientThread.IsBackground = false;
                        DealTcpClientThread.Start(tcpclient);
                    }
                }
                catch (ThreadAbortException)
                {
                    Thread.ResetAbort();
                }
                catch (Exception er)
                {
                    Console.WriteLine("StringServer.ListernThreadFunc()" + er.Message);
                }
                Thread.Sleep(1000);
            }
        }

        private void DealTcpClientThreadFunc(object obj)
        {
            //TCP
            TcpClient tcpclient = (TcpClient)obj;
            IPEndPoint ipe = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
            NetworkStream ns = tcpclient.GetStream();
            BinaryReader br = new BinaryReader(ns, Encoding.UTF8);
            BinaryWriter bw = new BinaryWriter(ns, Encoding.UTF8);
            if (m_writerList != null) m_writerList.Add(bw);
            if (m_readerList != null) m_readerList.Add(br);
            string read = "";
            string send = "";
            byte[] buffer = null;
            try
            {
                Console.WriteLine("建立连接" + ipe.Address.ToString() + ":" + ipe.Port.ToString());
                while ((m_exit == false) && (tcpclient.Client.Connected == true))
                {
                    bool feedback = false;
                    string error = "";
                    bool flag = false;

                    switch (m_mode)
                    {
                        case Enum_TcpWorkMode.Read:
                            read = br.ReadString();
                            flag = OnRecordReceived.Invoke(ref send, read, ref error);
                            break;
                        case Enum_TcpWorkMode.ReadSend:
                            read = br.ReadString();
                            flag = OnRecordReceived.Invoke(ref send, read, ref error);
                            if ((feedback) && (send != null) && (send != ""))
                            {
                                lock (bw)
                                {
                                    bw.Write(send);
                                }
                            }
                            break;
                        case Enum_TcpWorkMode.Send:
                            Thread.Sleep(100);
                            break;
                        case Enum_TcpWorkMode.SendRead:
                            Thread.Sleep(100);
                            break;
                        default:
                            break;
                    }
                    GC.Collect();
                }
            }
            catch (EndOfStreamException)
            {
                ;//unable to read beyond the end of stream
            }
            catch (IOException)
            {
                ;
            }
            catch (SocketException)
            {
                ;
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception er)
            {
                Console.WriteLine("StringServer.DealTcpClientThreadFunc()" + er.Message);
            }
            finally
            {
                if (br != null) br.Close();
                if (bw != null) bw.Close();
                if (ns != null)
                {
                    ns.Close();
                    ns.Dispose();
                }
                if (tcpclient != null)
                {
                    if (tcpclient.Client != null)
                    {
                        if (tcpclient.Client.Connected == true)
                        {
                            tcpclient.Client.Shutdown(SocketShutdown.Both);
                            tcpclient.Client.Close();
                        }
                    }
                    tcpclient.Close();
                }
                if (m_writerList != null) m_writerList.Remove(bw);
                if (m_readerList != null) m_readerList.Remove(br);
                Console.WriteLine("连接断开" + ipe.Address.ToString() + ":" + ipe.Port.ToString());
            }
        }

        private bool RecordReceivedFunc(ref string send, string read, ref string error)
        {
            error = "没有实现该消息处理函数";
            return false;
        }

    }
}
